package com.automotive.can1939.can;

import com.automotive.can1939.model.CanFrame;

import java.util.HashMap;
import java.util.Map;

/**
 * CAN数据解析器
 * 负责解析CAN帧数据并转换为可读的信息
 */
public class CanDataParser {
    
    /**
     * 解析结果类
     */
    public static class ParseResult {
        private String signalName;
        private String value;
        private String unit;
        private String description;
        
        public ParseResult(String signalName, String value, String unit, String description) {
            this.signalName = signalName;
            this.value = value;
            this.unit = unit;
            this.description = description;
        }
        
        // Getters
        public String getSignalName() { return signalName; }
        public String getValue() { return value; }
        public String getUnit() { return unit; }
        public String getDescription() { return description; }
        
        @Override
        public String toString() {
            return String.format("%s: %s %s (%s)", signalName, value, unit, description);
        }
    }
    
    /**
     * 解析CAN帧
     */
    public static ParseResult parseFrame(CanFrame frame) {
        int canId = frame.getCanId();
        byte[] data = frame.getData();

        switch (canId) {
            case CanConstants.CAN_ID_ENGINE_RPM:
                return parseEngineRpm(data);
            case CanConstants.CAN_ID_ENGINE_TEMP:
                return parseEngineTemperature(data);
            case CanConstants.CAN_ID_THROTTLE_POS:
                return parseThrottlePosition(data);
            case CanConstants.CAN_ID_VEHICLE_SPEED:
                return parseVehicleSpeed(data);
            case CanConstants.CAN_ID_WHEEL_SPEED:
                return parseWheelSpeed(data);
            case CanConstants.CAN_ID_BRAKE_PEDAL:
                return parseBrakePedal(data);
            case CanConstants.CAN_ID_ABS_STATUS:
                return parseAbsStatus(data);
            case CanConstants.CAN_ID_AIRCON_STATUS:
                return parseAirConditioning(data);
            case CanConstants.CAN_ID_FAN_SPEED:
                return parseFanSpeed(data);
            case CanConstants.CAN_ID_HEADLIGHT_STATUS:
                return parseHeadlightStatus(data);
            case CanConstants.CAN_ID_TURN_SIGNAL:
                return parseTurnSignal(data);
            case CanConstants.CAN_ID_DOOR_STATUS:
                return parseDoorStatus(data);
            case CanConstants.CAN_ID_WINDOW_STATUS:
                return parseWindowStatus(data);
            default:
                return parseUnknownFrame(frame);
        }
    }


    /**
     * 解析发动机转速
     */
    private static ParseResult parseEngineRpm(byte[] data) {
        if (data.length >= 4) {
            int rpm = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
            return new ParseResult("发动机转速", String.valueOf(rpm), "RPM", "当前发动机转速");
        }
        return new ParseResult("发动机转速", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析发动机温度
     */
    private static ParseResult parseEngineTemperature(byte[] data) {
        if (data.length >= 4) {
            int temp = data[3] & 0xFF;
            return new ParseResult("发动机温度", String.valueOf(temp), "°C", "发动机冷却液温度");
        }
        return new ParseResult("发动机温度", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析油门踏板位置
     */
    private static ParseResult parseThrottlePosition(byte[] data) {
        if (data.length >= 5) {
            int position = data[4] & 0xFF;
            return new ParseResult("油门位置", String.valueOf(position), "%", "油门踏板开度百分比");
        }
        return new ParseResult("油门位置", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析车速
     */
    private static ParseResult parseVehicleSpeed(byte[] data) {
        if (data.length >= 4) {
            int speed = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
            return new ParseResult("车速", String.valueOf(speed), "km/h", "当前车辆行驶速度");
        }
        return new ParseResult("车速", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析轮速
     */
    private static ParseResult parseWheelSpeed(byte[] data) {
        if (data.length >= 4) {
            int fl = data[0] & 0xFF; // 前左
            int fr = data[1] & 0xFF; // 前右
            int rl = data[2] & 0xFF; // 后左
            int rr = data[3] & 0xFF; // 后右
            String value = String.format("FL:%d FR:%d RL:%d RR:%d", fl, fr, rl, rr);
            return new ParseResult("轮速", value, "km/h", "四轮速度传感器数据");
        }
        return new ParseResult("轮速", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析制动踏板状态
     */
    private static ParseResult parseBrakePedal(byte[] data) {
        if (data.length >= 8) {
            boolean pressed = (data[7] & 0x01) != 0;
            String value = pressed ? "按下" : "释放";
            return new ParseResult("制动踏板", value, "", "制动踏板状态");
        }
        return new ParseResult("制动踏板", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析ABS状态
     */
    private static ParseResult parseAbsStatus(byte[] data) {
        if (data.length >= 7) {
            boolean active = (data[6] & 0x01) != 0;
            String value = active ? "激活" : "未激活";
            return new ParseResult("ABS状态", value, "", "防抱死制动系统状态");
        }
        return new ParseResult("ABS状态", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析空调状态
     */
    private static ParseResult parseAirConditioning(byte[] data) {
        if (data.length >= 2) {
            boolean on = (data[0] & 0x01) != 0;
            int temperature = data[1] & 0xFF;
            String value = String.format("%s, %d°C", on ? "开启" : "关闭", temperature);
            return new ParseResult("空调状态", value, "", "空调开关状态和设定温度");
        }
        return new ParseResult("空调状态", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析风扇速度
     */
    private static ParseResult parseFanSpeed(byte[] data) {
        if (data.length >= 3) {
            int speed = data[2] & 0xFF;
            return new ParseResult("风扇速度", String.valueOf(speed), "档", "空调风扇速度档位");
        }
        return new ParseResult("风扇速度", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析大灯状态
     */
    private static ParseResult parseHeadlightStatus(byte[] data) {
        if (data.length >= 2) {
            boolean lowBeam = (data[0] & 0x01) != 0;
            boolean highBeam = (data[1] & 0x01) != 0;
            String value;
            if (highBeam) {
                value = "远光灯";
            } else if (lowBeam) {
                value = "近光灯";
            } else {
                value = "关闭";
            }
            return new ParseResult("大灯状态", value, "", "前大灯开关状态");
        }
        return new ParseResult("大灯状态", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析转向灯状态
     */
    private static ParseResult parseTurnSignal(byte[] data) {
        if (data.length >= 3) {
            boolean left = (data[2] & 0x01) != 0;
            boolean right = (data[2] & 0x02) != 0;
            String value;
            if (left && right) {
                value = "双闪";
            } else if (left) {
                value = "左转";
            } else if (right) {
                value = "右转";
            } else {
                value = "关闭";
            }
            return new ParseResult("转向灯", value, "", "转向指示灯状态");
        }
        return new ParseResult("转向灯", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析车门状态
     */
    private static ParseResult parseDoorStatus(byte[] data) {
        if (data.length >= 4) {
            boolean fl = (data[0] & 0x01) != 0; // 前左门
            boolean fr = (data[1] & 0x01) != 0; // 前右门
            boolean rl = (data[2] & 0x01) != 0; // 后左门
            boolean rr = (data[3] & 0x01) != 0; // 后右门
            
            StringBuilder sb = new StringBuilder();
            if (fl) sb.append("前左 ");
            if (fr) sb.append("前右 ");
            if (rl) sb.append("后左 ");
            if (rr) sb.append("后右 ");
            
            String value = sb.length() > 0 ? sb.toString().trim() + "门开启" : "所有门关闭";
            return new ParseResult("车门状态", value, "", "车门开关状态");
        }
        return new ParseResult("车门状态", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析车窗状态
     */
    private static ParseResult parseWindowStatus(byte[] data) {
        if (data.length >= 4) {
            int fl = data[0] & 0xFF; // 前左窗位置
            int fr = data[1] & 0xFF; // 前右窗位置
            int rl = data[2] & 0xFF; // 后左窗位置
            int rr = data[3] & 0xFF; // 后右窗位置
            
            String value = String.format("FL:%d%% FR:%d%% RL:%d%% RR:%d%%", fl, fr, rl, rr);
            return new ParseResult("车窗状态", value, "", "车窗开启百分比");
        }
        return new ParseResult("车窗状态", "无效数据", "", "数据长度不足");
    }
    
    /**
     * 解析未知帧
     */
    private static ParseResult parseUnknownFrame(CanFrame frame) {
        String value = frame.getDataHexString();
        String description = CanTestDataGenerator.getCanIdDescription(frame.getCanId());
        return new ParseResult("未知信号", value, "", description);
    }
    
    /**
     * 批量解析CAN帧
     */
    public static Map<Integer, ParseResult> parseFrames(CanFrame[] frames) {
        Map<Integer, ParseResult> results = new HashMap<>();
        for (CanFrame frame : frames) {
            results.put(frame.getCanId(), parseFrame(frame));
        }
        return results;
    }
    
    /**
     * 获取信号的原始数值（用于图表显示等）
     */
    public static double getNumericValue(CanFrame frame) {
        int canId = frame.getCanId();
        byte[] data = frame.getData();

        switch (canId) {
            case CanConstants.CAN_ID_ENGINE_RPM: // 发动机转速
                if (data.length >= 4) {
                    return ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
                }
                break;
            case CanConstants.CAN_ID_ENGINE_TEMP: // 发动机温度
                if (data.length >= 4) {
                    return data[3] & 0xFF;
                }
                break;
            case CanConstants.CAN_ID_THROTTLE_POS: // 油门位置
                if (data.length >= 5) {
                    return data[4] & 0xFF;
                }
                break;
            case CanConstants.CAN_ID_VEHICLE_SPEED: // 车速
                if (data.length >= 4) {
                    return ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
                }
                break;
        }

        return 0.0;
    }

}